//
//  HMSegmentedControl.h
//  HMSegmentedControl
//
//  Created by Hesham Abd-Elmegid on 23/12/12.
//  Copyright (c) 2012-2015 Hesham Abd-Elmegid. All rights reserved.
//
//  TYSegmentedControl is a custom copy of HMSegmentedControl.
//

#import <math.h>
#import "TYSegmentAnimator.h"
#import "TYSegmentedControl.h"
#import "TYSegmentIndicatorView.h"
#import "TYSegmentCollectionView.h"
#import <TYUIKit/UIScreen+TYFrame.h>
#import "TYUIKit/TYUIKit-umbrella.h"

TYSegmentLength  const TYSegmentLengthDynamic = -1;
static NSString *const TYSegmentCellIdentifer = @"TYSegmentCellIdentifer";

@interface TYSegmentedControl () <UICollectionViewDelegate, UICollectionViewDataSource>

@property (nonatomic, assign) NSInteger selectedIndex;

@property (nonatomic, assign) CGFloat   innerCellSpacing;

@property (nonatomic, assign) CGFloat   titleLabelZoomScale;

@property (nonatomic, assign) BOOL      isTransitionAnimating;

@property (nonatomic, assign) CGPoint   lastContentViewContentOffset;

@property (nonatomic, assign) NSInteger scrollingTargetIndex;

@property (nonatomic, strong) TYSegmentIndicatorView        *indicatorView;

@property (nonatomic, strong) TYSegmentCollectionView       *collectionView;

@property (nonatomic, strong) NSMutableArray<TYSegmentCellModel *> *dataSource;

@property (nonatomic, assign) CGFloat                       totalWidth;

@property (nonatomic, strong) NSMutableArray *redPoints;


@property(nonatomic, assign, readonly) BOOL isCharacterTable;
@end

@implementation TYSegmentedControl

- (void)dealloc {
    if (self.contentScrollView) {
        [self.contentScrollView removeObserver:self forKeyPath:@"contentOffset"];
    }
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self initDefaultPropertys];
        [self initViews];
        self.redPoints = [[NSMutableArray alloc] init];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        [self initDefaultPropertys];
        [self initViews];
    }
    return self;
}

- (BOOL)isCharacterTable{
    return self.segmentType == TYSegmentTypeCharacterTable;
}

- (void)initDefaultPropertys
{
    _dataSource = [NSMutableArray array];
    _selectedIndex = 0;
    _itemWidthIncrement = TY_ScreenAdaptionLength(10);
    _itemSpacing = TY_ScreenAdaptionLength(20);
    
    _imageSize = CGSizeMake(20.f, 20.f);
    _imageRenderMode = UIImageRenderingModeAlwaysTemplate;
    _imageBundle = [NSBundle mainBundle];
    _segmentType = TYSegmentTypeOnlyTitle;
    
    _averageCellSpacingEnabled = NO;
    _itemWidth = TYSegmentLengthDynamic;
    _indicatorWidth = TYSegmentLengthDynamic;
    _contentAlignment = TYSegmentAlignmentLeft;
    _indicatorStyle = TYSegmentIndicatorStyleLine;
    _indicatorPosition = TYSegmentIndicatorPositionBottom;
    
    _itemWidthZoomScrollGradientEnabled = NO;
    _cellBackgroundUnselectedColor = [UIColor clearColor];
    _cellBackgroundSelectedColor = [UIColor clearColor];
    
    _contentEdgeInsetLeft = 0.f;
    _contentEdgeInsetRight = 0.f;
    _selectedAnimationEnabled = YES;
    _selectedAnimationDuration = 0.25;
    _scrollingTargetIndex = -1;
    _selectedAnimationEnabled = YES;
    _indicatorVerticalOffset = 0;
    
    // -- title properties
    _titleColor = [UIColor blackColor];
    _titleFont = [UIFont systemFontOfSize:15];
    _titleSelectedColor = [UIColor redColor];
    _titleLabelZoomEnabled = YES;
    _titleLabelMaskEnabled = NO;
    _titleColorGradientEnabled = YES;
    _titleLabelZoomScrollGradientEnabled = YES;
    _titleLabelStrokeWidthEnabled = NO;
    _titleLabelSelectedStrokeWidth = -3;
}

- (void)initViews {
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    _collectionView = [[TYSegmentCollectionView alloc] initWithFrame:self.bounds collectionViewLayout:layout];
    self.collectionView.backgroundColor = [UIColor clearColor];
    self.collectionView.showsHorizontalScrollIndicator = NO;
    self.collectionView.showsVerticalScrollIndicator = NO;
    self.collectionView.scrollsToTop = NO;
    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;
    [self.collectionView registerClass:TYSegmentCell.class forCellWithReuseIdentifier:TYSegmentCellIdentifer];
    if (@available(iOS 11.0, *)) {
        self.collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }
    [self addSubview:self.collectionView];
    
    self.indicatorView = [[TYSegmentIndicatorView alloc] initWithFrame:CGRectZero];
    self.indicatorView.veticalOffset = self.indicatorVerticalOffset;
    [self.collectionView addSubview:self.indicatorView];
}

- (void)setContentInset:(UIEdgeInsets)contentInset{
    _contentInset = contentInset;
    self.collectionView.contentInset = contentInset;
//    CGRect frame = CGRectMake(contentInset.left, contentInset.top, self.collectionView.ty_width - contentInset.left - contentInset.right, self.collectionView.ty_height - contentInset.top - contentInset.bottom);
//    self.collectionView.frame = frame;
}

- (void)setIndicatorLineViewHeight:(TYSegmentLength)indicatorLineViewHeight{
    self.indicatorView.indicatorLineViewHeight = indicatorLineViewHeight;
}

- (void)reloadData {
    [self reloadDataSource];
    [self.collectionView.collectionViewLayout invalidateLayout];
    [self.collectionView reloadData];
}


- (void)reloadDataSource {
    if (self.selectedIndex < 0 || self.selectedIndex >= self.dataSource.count) {
        self.selectedIndex = 0;
    }
    /*
    *当所指向的元素下标不存在了，默认指向最后一个元素,add by:盲僧
    */
    long num = MAX(self.titles.count, MAX(self.imageNames.count, self.imageUrls.count));
    if(self.selectedIndex>= num) {
       self.selectedIndex = (num-1);
    }
    
    __block CGFloat totalItemWidth = [self getContentEdgeInsetLeft];
    self.innerCellSpacing = self.itemSpacing;
    
    CGFloat totalCellWidth = 0;
    CGRect selectedCellFrame = CGRectZero;
    
    if (!self.titleLabelZoomEnabled) {
        self.titleLabelZoomScale = 0;
    } else {
        self.titleLabelZoomScale = self.titleSelectedFont.pointSize / self.titleFont.pointSize;
    }
    self.dataSource = [[NSMutableArray alloc] init];
    for (NSUInteger i = 0; i < num; i++) {
        TYSegmentCellModel *cellModel = [[TYSegmentCellModel alloc] init];
        [self.dataSource addObject:cellModel];
        cellModel.index = i;
        
        if (self.segmentType == TYSegmentTypeOnlyImage) {
            cellModel.imageName = self.imageNames.count > i ? [self.imageNames objectAtIndex:i] : nil;
            cellModel.imageBundle = _imageBundle;
            cellModel.imageUrl = self.imageUrls.count > i ? [self.imageUrls objectAtIndex:i] : nil;
        } else if (self.segmentType == TYSegmentTypeOnlyTitle) {
            cellModel.title = [self.titles objectAtIndex:i];
        }
        else if (self.segmentType == TYSegmentTypeCharacterTable){
            cellModel.title = [self.titles objectAtIndex:i];
            cellModel.isCharacterTable = YES;
        }
        else {
            cellModel.title = [self.titles objectAtIndex:i];
            cellModel.imageName = self.imageNames.count > i ? [self.imageNames objectAtIndex:i] : nil;
            cellModel.imageUrl = self.imageUrls.count > i ? [self.imageUrls objectAtIndex:i] : nil;
        }
        cellModel.imageRenderMode = _imageRenderMode;
        cellModel.titleImageSpacing = self.imageTitleSpacing;
        cellModel.imageSize = self.imageSize;
        cellModel.cellWidth = [self getCellWidthWithIndex:i] + self.itemWidthIncrement;
        cellModel.cellWidthNormalZoomScale = 1;
        cellModel.selectedAnimationEnabled = self.selectedAnimationEnabled;
        cellModel.selectedAnimationDuration = self.selectedAnimationDuration;
        cellModel.cellSpacing = self.innerCellSpacing;
        cellModel.showRedPoint = [self.redPoints containsObject:@(i)];
        
        //--- backgroud color
        cellModel.sepratorLineShowEnabled = self.separatorLineShowEnabled;
        cellModel.separatorLineColor = self.separatorLineColor;
        cellModel.separatorLineSize = self.separatorLineSize;
        cellModel.backgroundViewMaskFrame = CGRectZero;
        cellModel.cellBackgroundColorGradientEnabled = self.cellBackgroundColorGradientEnabled;
        cellModel.cellBackgroundSelectedColor = self.cellBackgroundSelectedColor;
        cellModel.cellBackgroundUnselectedColor = self.cellBackgroundUnselectedColor;
        cellModel.cellLayerRadius = self.cellLayerRadius;
        
        if (i == self.selectedIndex) {
            cellModel.selected = YES;
            cellModel.cellWidthCurrentZoomScale = cellModel.cellWidthSelectedZoomScale;
            selectedCellFrame = [self getTargetCellFrame:i];
        } else {
            cellModel.selected = NO;
            cellModel.cellWidthCurrentZoomScale = cellModel.cellWidthNormalZoomScale;
        }
        
        totalCellWidth += cellModel.cellWidth;
        
        if (i == self.titles.count - 1) {
            totalItemWidth += cellModel.cellWidth + [self getContentEdgeInsetRight];
            cellModel.sepratorLineShowEnabled = self.separatorLineShowEnabled;
        }else {
            totalItemWidth += cellModel.cellWidth + self.innerCellSpacing;
        }
        
        if (self.titles.count <= 0 || self.indicatorStyle == TYSegmentIndicatorStyleNone) {
            self.indicatorView.hidden = YES;
        }else {
            self.indicatorView.hidden = NO;
            self.indicatorView.indicatorLineWidth = self.indicatorWidth;
            self.indicatorView.indicatorLineViewColor = self.indicatorColor;
            
            TYIndicatorModel *indicatorParamsModel = [[TYIndicatorModel alloc] init];
            indicatorParamsModel.selectedIndex = self.selectedIndex;
            indicatorParamsModel.selectedCellFrame = selectedCellFrame;
            indicatorParamsModel.indicatorStyle = self.indicatorStyle;
            [self.indicatorView refreshState:indicatorParamsModel];
            
        }
        
        [self applyTitlePropertisWithCellModel:cellModel];
        
        if (i == self.selectedIndex) {
            cellModel.titleCurrentColor = cellModel.titleSelectedColor;
            cellModel.titleLabelCurrentZoomScale = cellModel.titleLabelSelectedZoomScale;
            cellModel.titleLabelCurrentStrokeWidth= cellModel.titleLabelSelectedStrokeWidth;
        } else {
            cellModel.titleCurrentColor = cellModel.titleNormalColor;
            cellModel.titleLabelCurrentZoomScale = cellModel.titleLabelNormalZoomScale;
            cellModel.titleLabelCurrentStrokeWidth = cellModel.titleLabelNormalStrokeWidth;
        }
    }
    
    if (self.averageCellSpacingEnabled && totalItemWidth < self.bounds.size.width) {
        
        NSInteger cellSpacingItemCount = self.dataSource.count - 1;
        CGFloat totalCellSpacingWidth = self.bounds.size.width - totalCellWidth;
        
        if (self.contentEdgeInsetLeft == TYSegmentLengthDynamic) {
            cellSpacingItemCount += 1;
        }else {
            totalCellSpacingWidth -= self.contentEdgeInsetLeft;
        }
        
        if (self.contentEdgeInsetRight == TYSegmentLengthDynamic) {
            cellSpacingItemCount += 1;
        }else {
            totalCellSpacingWidth -= self.contentEdgeInsetRight;
        }
        
        CGFloat cellSpacing = 0;
        if (cellSpacingItemCount > 0) {
            cellSpacing = totalCellSpacingWidth/cellSpacingItemCount;
        }
        self.innerCellSpacing = cellSpacing;
        [self.dataSource enumerateObjectsUsingBlock:^(TYSegmentCellModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            obj.cellSpacing = self.innerCellSpacing;
        }];
    }
    
    __block CGFloat frameXOfSelectedCell = self.innerCellSpacing;
    __block CGFloat selectedCellWidth = 0;
    totalItemWidth = [self getContentEdgeInsetLeft];
    [self.dataSource enumerateObjectsUsingBlock:^(TYSegmentCellModel * cellModel, NSUInteger idx, BOOL * _Nonnull stop) {
        if (idx < self.selectedIndex) {
            frameXOfSelectedCell += cellModel.cellWidth + self.innerCellSpacing;
        }else if (idx == self.selectedIndex) {
            selectedCellWidth = cellModel.cellWidth;
        }
        if (idx == self.dataSource.count - 1) {
            totalItemWidth += cellModel.cellWidth + [self getContentEdgeInsetRight];
        }else {
            totalItemWidth += cellModel.cellWidth + self.innerCellSpacing;
        }
    }];
    
    CGFloat minX = 0;
    CGFloat maxX = totalItemWidth - self.bounds.size.width;
    CGFloat targetX = frameXOfSelectedCell - self.bounds.size.width/2.0 + selectedCellWidth/2.0;
    [self.collectionView setContentOffset:CGPointMake(MAX(MIN(maxX, targetX), minX), 0) animated:NO];
    
    if (CGRectEqualToRect(self.contentScrollView.frame, CGRectZero) && self.contentScrollView.superview != nil) {
        UIView *parentView = self.contentScrollView.superview;
        while (parentView != nil && CGRectEqualToRect(parentView.frame, CGRectZero)) {
            parentView = parentView.superview;
        }
        [parentView setNeedsLayout];
        [parentView layoutIfNeeded];
    }
    self.totalWidth = totalItemWidth;
    
    [self.contentScrollView setContentOffset:CGPointMake(self.selectedIndex*self.contentScrollView.bounds.size.width, 0) animated:NO];
}

- (void)applyIndicatorPropertiesWithCellModle:(TYSegmentCellModel *)cellModel index:(NSUInteger)index {
    
}

- (void)applyTitlePropertisWithCellModel:(TYSegmentCellModel *)model {
    model.titleFont = self.titleFont;
    model.titleSelectedFont = self.titleSelectedFont;
    model.titleNormalColor = self.titleColor;
    model.titleSelectedColor = self.titleSelectedColor;
    model.titleLabelMaskEnabled = self.titleLabelMaskEnabled;
    model.titleLabelZoomEnabled = self.titleLabelZoomEnabled;
    model.titleLabelNormalZoomScale = 1;
    model.titleLabelSelectedZoomScale = self.titleLabelZoomScale;
    model.titleLabelStrokeWidthEnabled = self.titleLabelStrokeWidthEnabled;
    model.titleLabelNormalStrokeWidth = 0;
    model.titleLabelSelectedStrokeWidth = self.titleLabelSelectedStrokeWidth;
}


- (void)selectCellAtIndex:(NSInteger)targetIndex selectedType:(TYSegmentItemSelectType)selectedType {
    if (targetIndex < 0 || targetIndex >= self.dataSource.count) {
        return;
    }
    
    if (self.selectedIndex == targetIndex) {
        if (selectedType == TYSegmentItemSelectTypeClick) {
            if ([self.delegate respondsToSelector:@selector(segmentedControl:didSelectAtIndex:)]) {
                [self.delegate segmentedControl:self didSelectAtIndex:self.selectedIndex];
            }
        }
        self.scrollingTargetIndex = -1;
        return;
    }
    
    
    
    //通知子类刷新当前选中的和将要选中的cellModel
    TYSegmentCellModel *lastCellModel;
    if (self.selectedIndex < self.dataSource.count) {
        lastCellModel =  [self.dataSource objectAtIndex:self.selectedIndex];
    }
    lastCellModel.selectedType = selectedType;
    TYSegmentCellModel *selectedCellModel;
    if (targetIndex < self.dataSource.count) {
       selectedCellModel = [self.dataSource objectAtIndex:targetIndex];
    }
    selectedCellModel.selectedType = selectedType;
    [self refreshSelectedCellModel:selectedCellModel unselectedCellModel:lastCellModel];
    
    //刷新当前选中的和将要选中的cell
    TYSegmentCell *lastCell = (TYSegmentCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.selectedIndex inSection:0]];
    [lastCell reloadData:lastCellModel];
    TYSegmentCell *selectedCell = (TYSegmentCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0]];
    [selectedCell reloadData:selectedCellModel];
    
    if (self.scrollingTargetIndex != -1 && self.scrollingTargetIndex != targetIndex && self.scrollingTargetIndex < self.dataSource.count) {
        TYSegmentCellModel *scrollingTargetCellModel = [self.dataSource objectAtIndex:self.scrollingTargetIndex];
        scrollingTargetCellModel.selected = NO;
        scrollingTargetCellModel.selectedType = selectedType;
        [self refreshSelectedCellModel:selectedCellModel unselectedCellModel:scrollingTargetCellModel];
        TYSegmentCell *scrollingTargetCell = (TYSegmentCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.scrollingTargetIndex inSection:0]];
        [scrollingTargetCell reloadData:scrollingTargetCellModel];
    }
    
    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
    NSInteger lastSelectIndex = self.selectedIndex;
    self.selectedIndex = targetIndex;
    
    if (selectedType == TYSegmentItemSelectTypeClick) {
        if ([self.delegate respondsToSelector:@selector(segmentedControl:didSelectAtIndex:)]) {
            [self.delegate segmentedControl:self didSelectAtIndex:self.selectedIndex];
        }
    }
    
    self.scrollingTargetIndex = -1;
    
    
    CGRect clickedCellFrame = [self getTargetCellFrame:targetIndex];
    
    selectedCellModel.selectedType = selectedType;
    TYIndicatorModel *indicatorParamsModel = [[TYIndicatorModel alloc] init];
    indicatorParamsModel.lastSelectedIndex = lastSelectIndex;
    indicatorParamsModel.selectedIndex = targetIndex;
    indicatorParamsModel.selectedCellFrame = clickedCellFrame;
    indicatorParamsModel.selectedType = selectedType;
    [self.indicatorView selectedCell:indicatorParamsModel];
    
    
    [selectedCell reloadData:selectedCellModel];
    return;
}


- (void)contentOffsetOfContentScrollViewDidChanged:(CGPoint)contentOffset {
    CGFloat ratio = contentOffset.x/self.contentScrollView.bounds.size.width;
    if (ratio > self.dataSource.count - 1 || ratio < 0) {
        return;
    }
    if (contentOffset.x == 0 && self.selectedIndex == 0 && self.lastContentViewContentOffset.x == 0) {
        return;
    }
    CGFloat maxContentOffsetX = self.contentScrollView.contentSize.width - self.contentScrollView.bounds.size.width;
    if (contentOffset.x == maxContentOffsetX && self.selectedIndex == self.dataSource.count - 1 && self.lastContentViewContentOffset.x == maxContentOffsetX) {
        return;
    }
    ratio = MAX(0, MIN(self.dataSource.count - 1, ratio));
    NSInteger baseIndex = floorf(ratio);
    CGFloat remainderRatio = ratio - baseIndex;
    
    if (remainderRatio == 0) {
        if (!(self.lastContentViewContentOffset.x == contentOffset.x && self.selectedIndex == baseIndex)) {
            [self scrollSelectItemAtIndex:baseIndex];
        }
        
    }else {
        if (fabs(ratio - self.selectedIndex) > 1) {
            NSInteger targetIndex = baseIndex;
            if (ratio < self.selectedIndex) {
                targetIndex = baseIndex + 1;
            }
            [self scrollSelectItemAtIndex:targetIndex];
        }
        
        if (self.selectedIndex == baseIndex) {
            self.scrollingTargetIndex = baseIndex + 1;
        }else {
            self.scrollingTargetIndex = baseIndex;
        }
    }
    
    [self contentOffsetForIndicatorViewDidChange:contentOffset];
    
}

- (void)contentOffsetForIndicatorViewDidChange:(CGPoint)contentOffset {
    CGFloat ratio = contentOffset.x/self.contentScrollView.bounds.size.width;
    if (ratio > self.dataSource.count - 1 || ratio < 0) {
        //超过了边界，不需要处理
        return;
    }
    ratio = MAX(0, MIN(self.dataSource.count - 1, ratio));
    NSInteger baseIndex = floorf(ratio);
    if (baseIndex + 1 >= self.dataSource.count) {
        //右边越界了，不需要处理
        return;
    }
    CGFloat remainderRatio = ratio - baseIndex;
    
    CGRect leftCellFrame = [self getTargetCellFrame:baseIndex];
    CGRect rightCellFrame = [self getTargetCellFrame:baseIndex + 1];
    
    TYIndicatorModel *indicatorParamsModel = [[TYIndicatorModel alloc] init];
    indicatorParamsModel.selectedIndex = self.selectedIndex;
    indicatorParamsModel.leftIndex = baseIndex;
    indicatorParamsModel.leftCellFrame = leftCellFrame;
    indicatorParamsModel.rightIndex = baseIndex + 1;
    indicatorParamsModel.rightCellFrame = rightCellFrame;
    indicatorParamsModel.percent = remainderRatio;
    if (remainderRatio == 0) {
        [self.indicatorView contentScrollViewDidScroll:indicatorParamsModel];
    } else {
        
        TYSegmentCellModel *leftCellModel = (TYSegmentCellModel *)self.dataSource[baseIndex];
        leftCellModel.selectedType = TYSegmentItemSelectTypeUnknow;
        TYSegmentCellModel *rightCellModel = (TYSegmentCellModel *)self.dataSource[baseIndex + 1];
        rightCellModel.selectedType = TYSegmentItemSelectTypeUnknow;
        [self refreshLeftCellModel:leftCellModel rightCellModel:rightCellModel ratio:remainderRatio];
        
        
        TYSegmentCell *leftCell = (TYSegmentCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:baseIndex inSection:0]];
        [leftCell reloadData:leftCellModel];
        TYSegmentCell *rightCell = (TYSegmentCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:baseIndex + 1 inSection:0]];
        [rightCell reloadData:rightCellModel];
        [self.indicatorView contentScrollViewDidScroll:indicatorParamsModel];
    }
}


- (void)refreshSelectedCellModel:(TYSegmentCellModel *)selectedCellModel unselectedCellModel:(TYSegmentCellModel *)unselectedCellModel {
    selectedCellModel.selected = YES;
    unselectedCellModel.selected = NO;
    
    unselectedCellModel.titleCurrentColor = unselectedCellModel.titleNormalColor;
    unselectedCellModel.titleLabelCurrentZoomScale = unselectedCellModel.titleLabelNormalZoomScale;
    unselectedCellModel.titleLabelCurrentStrokeWidth = unselectedCellModel.titleLabelNormalStrokeWidth;
    
    selectedCellModel.titleCurrentColor = selectedCellModel.titleSelectedColor;
    selectedCellModel.titleLabelCurrentZoomScale = selectedCellModel.titleLabelSelectedZoomScale;
    selectedCellModel.titleLabelCurrentStrokeWidth = selectedCellModel.titleLabelSelectedStrokeWidth;
}

- (void)refreshLeftCellModel:(TYSegmentCellModel *)leftCellModel rightCellModel:(TYSegmentCellModel *)rightCellModel ratio:(CGFloat)ratio {
    if (self.itemWidthZoomScrollGradientEnabled) {
        if (leftCellModel.selected) {
            leftCellModel.cellBackgroundSelectedColor = [TYSegmentAnimator interpolationColorFrom:self.cellBackgroundSelectedColor to:self.cellBackgroundUnselectedColor percent:ratio];
            leftCellModel.cellBackgroundUnselectedColor = self.cellBackgroundUnselectedColor;
        }else {
            leftCellModel.cellBackgroundUnselectedColor = [TYSegmentAnimator interpolationColorFrom:self.cellBackgroundSelectedColor to:self.cellBackgroundUnselectedColor percent:ratio];
            leftCellModel.cellBackgroundSelectedColor = self.cellBackgroundSelectedColor;
        }
        if (rightCellModel.selected) {
            rightCellModel.cellBackgroundSelectedColor = [TYSegmentAnimator interpolationColorFrom:self.cellBackgroundUnselectedColor to:self.cellBackgroundSelectedColor percent:ratio];
            rightCellModel.cellBackgroundUnselectedColor = self.cellBackgroundUnselectedColor;
        }else {
            rightCellModel.cellBackgroundUnselectedColor = [TYSegmentAnimator interpolationColorFrom:self.cellBackgroundUnselectedColor to:self.cellBackgroundSelectedColor percent:ratio];
            rightCellModel.cellBackgroundSelectedColor = self.cellBackgroundSelectedColor;
        }
    }
    
    if (self.titleLabelZoomEnabled && self.titleLabelZoomScrollGradientEnabled) {
        leftCellModel.titleLabelCurrentZoomScale = [TYSegmentAnimator interpolationFrom:self.titleLabelZoomScale to:1.0 percent:ratio];
        rightCellModel.titleLabelCurrentZoomScale = [TYSegmentAnimator interpolationFrom:1.0 to:self.titleLabelZoomScale percent:ratio];
    }
    
    if (self.titleLabelStrokeWidthEnabled) {
        leftCellModel.titleLabelCurrentStrokeWidth = [TYSegmentAnimator interpolationFrom:leftCellModel.titleLabelSelectedStrokeWidth to:leftCellModel.titleLabelNormalStrokeWidth percent:ratio];
        rightCellModel.titleLabelCurrentStrokeWidth = [TYSegmentAnimator interpolationFrom:rightCellModel.titleLabelNormalStrokeWidth to:rightCellModel.titleLabelSelectedStrokeWidth percent:ratio];
    }
    
    if (self.titleColorGradientEnabled) {
        leftCellModel.titleCurrentColor = [TYSegmentAnimator interpolationColorFrom:self.titleSelectedColor to:self.titleColor percent:ratio];
        rightCellModel.titleCurrentColor = [TYSegmentAnimator interpolationColorFrom:self.titleColor to:self.titleSelectedColor percent:ratio];
    }
}

#pragma mark - layoutSubView

- (void)layoutSubviews
{
    [super layoutSubviews];
    [self reloadData];
    
    if (self.totalWidth < self.bounds.size.width && self.collectionView.contentSize.width <= self.bounds.size.width ) {
        if (self.contentAlignment == TYSegmentAlignmentLeft) {
            self.collectionView.frame = CGRectMake(0, 0, self.bounds.size.width, floor(self.bounds.size.height));
        } else if (self.contentAlignment == TYSegmentAlignmentCenter) {
            self.collectionView.frame = CGRectMake(floor((self.bounds.size.width - self.totalWidth )/ 2.f), 0, self.totalWidth, self.bounds.size.height);
        } else {
            self.collectionView.frame = CGRectMake(floor(self.bounds.size.width - self.totalWidth), 0, self.totalWidth, self.bounds.size.height);
        }
        
    } else {
        self.collectionView.frame = CGRectMake(0, 0, self.bounds.size.width, floor(self.bounds.size.height));
    }
    self.contentInset = self.contentInset;
}

#pragma mark - <UICollectionViewDataSource, UICollectionViewDelegate>

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.dataSource.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    return [collectionView dequeueReusableCellWithReuseIdentifier:TYSegmentCellIdentifer forIndexPath:indexPath];
}

- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    TYSegmentCellModel *cellModel = self.dataSource.count > indexPath.item ? self.dataSource[indexPath.item] : nil;
    cellModel.selectedType = TYSegmentItemSelectTypeUnknow;
    TYSegmentCell* segCell = (TYSegmentCell *)cell;
    [segCell reloadData:cellModel];
    __weak typeof(self) weakSelf = self;
    segCell.characterTableselectedCallback = ^{
        [weakSelf collectionView:weakSelf.collectionView didSelectItemAtIndexPath:indexPath];
    };
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    BOOL isTransitionAnimating = NO;
    for (TYSegmentCellModel *cellModel in self.dataSource) {
        if (cellModel.isTransitionAnimating) {
            isTransitionAnimating = YES;
            break;
        }
    }
    
    if (!isTransitionAnimating) {
        [self clickSelectItemAtIndex:indexPath.row];
    }
}

#pragma mark - <UICollectionViewDelegateFlowLayout>

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(0, [self getContentEdgeInsetLeft], 0, [self getContentEdgeInsetRight]);
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return CGSizeMake(self.dataSource[indexPath.item].cellWidth, self.collectionView.ty_height - self.contentInset.top - self.contentInset.bottom);
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return self.innerCellSpacing;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    return self.innerCellSpacing;
}


#pragma mark - getter

- (CGRect)getTargetCellFrame:(NSInteger)targetIndex
{
    CGFloat x = [self getContentEdgeInsetLeft];
    for (int i = 0; i < targetIndex; i ++) {
        TYSegmentCellModel *cellModel = self.dataSource[i];
        x += cellModel.cellWidth + self.innerCellSpacing;
    }
    CGFloat width = self.dataSource[targetIndex].cellWidth;
    return CGRectMake(x, 0, width, self.collectionView.ty_height - self.contentInset.top - self.contentInset.bottom);
}

- (CGFloat)getContentEdgeInsetLeft {
    if (self.contentEdgeInsetLeft == TYSegmentLengthDynamic) {
        return self.innerCellSpacing;
    }
    return self.contentEdgeInsetLeft;
}

- (CGFloat)getContentEdgeInsetRight {
    if (self.contentEdgeInsetRight == TYSegmentLengthDynamic) {
        return self.innerCellSpacing;
    }
    return self.contentEdgeInsetRight;
}

- (CGFloat)getCellWidthWithIndex:(NSUInteger)index {
    if (self.itemWidth == TYSegmentLengthDynamic) {
        NSMutableDictionary *attr = [NSMutableDictionary dictionary];
        if (self.titleLabelStrokeWidthEnabled) {
            [attr setObject:@(self.titleLabelSelectedStrokeWidth) forKey:NSStrokeWidthAttributeName];
        }
        [attr setObject:self.titleFont forKey:NSFontAttributeName];
        CGFloat titleWidth = 0.f;
        if (self.titles && self.titles.count > index) {
            if (self.isCharacterTable) {
                return ceil(TY_ScreenAdaptionLength(45)) * self.titles[index].length;
            }
            titleWidth = ceilf([self.titles[index] boundingRectWithSize:CGSizeMake(MAXFLOAT, self.bounds.size.height)
                                                                options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading
                                                             attributes:attr context:nil].size.width);
        }
        if (self.segmentType == TYSegmentTypeOnlyTitle) {
            return titleWidth;
        } else if (self.segmentType == TYSegmentTypeOnlyImage)  {
            return self.imageSize.width;
        } else {
            return MAX(titleWidth, self.imageSize.width);
        }
    }else {
        return self.itemWidth;
    }
}

#pragma mark - setter

- (void)setIndicatorVerticalOffset:(CGFloat)indicatorVerticalOffset {
    _indicatorVerticalOffset = indicatorVerticalOffset;
    self.indicatorView.veticalOffset = _indicatorVerticalOffset;
}

- (void)setDefaultSelectedIndex:(NSInteger)defaultSelectedIndex
{
    _defaultSelectedIndex = defaultSelectedIndex;
    
    self.selectedIndex = defaultSelectedIndex;
}

- (void)setContentScrollView:(UIScrollView *)contentScrollView
{
    if (_contentScrollView != nil) {
        [_contentScrollView removeObserver:self forKeyPath:@"contentOffset"];
    }
    _contentScrollView = contentScrollView;
    
    self.contentScrollView.scrollsToTop = NO;
    [self.contentScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)setTitles:(NSArray<NSString *> *)titles {
    if (titles.count > 0) {
        if ([self superview]) {
            NSString *titleCompents = [titles componentsJoinedByString:@""];
            if (_titles != nil && _titles.count >0) {
                NSString *currentTitleCompents = [_titles componentsJoinedByString:@""];
                if ([currentTitleCompents isEqualToString:titleCompents]) {
                    return;
                }
            }
        }
        _titles = titles;
        [self reloadData];
    }
}

- (void)setImageNames:(NSArray<NSString *> *)imageNames {
    if (imageNames.count > 0) {
        _imageNames = imageNames;
        [self reloadData];
    }
}

#pragma mark - select index

- (void)clickSelectItemAtIndex:(NSInteger)index {
    [self selectCellAtIndex:index selectedType:TYSegmentItemSelectTypeClick];
}

- (void)scrollSelectItemAtIndex:(NSInteger)index {
    [self selectCellAtIndex:index selectedType:TYSegmentItemSelectTypeScroll];
}

- (void)selectAtIndex:(NSInteger)index {
    [self selectCellAtIndex:index selectedType:TYSegmentItemSelectTypeCode];
}

#pragma mark - KVO

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"contentOffset"]) {
        CGPoint contentOffset = [change[NSKeyValueChangeNewKey] CGPointValue];
        if ((self.contentScrollView.isTracking || self.contentScrollView.isDecelerating)) {
            //只处理用户滚动的情况
            [self contentOffsetOfContentScrollViewDidChanged:contentOffset];
        }
        self.lastContentViewContentOffset = contentOffset;
    }
}

- (BOOL)isAccessibilityElement {
    return NO;
}

- (void)showRedPointAtIndexs:(NSArray<NSNumber *> *)indexs {
    for (NSNumber *number in indexs) {
        if (![self.redPoints containsObject:number]) {
            [self.redPoints addObject:number];
        }
    }
    [self reloadData];
}

- (void)showRedPointAtIndex:(NSInteger)index {
    if ([self.redPoints containsObject:@(index)]) {
        return;
    }
    
    [self.redPoints addObject:@(index)];
    [self reloadData];
}

- (void)hideRedPointAtIndex:(NSInteger)index {
    if (![self.redPoints containsObject:@(index)]) {
        return;
    }
    [self.redPoints removeObject:@(index)];
    [self reloadData];
}


@end





